package br.rui.cartoes.negocio;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

import br.rui.cartoes.dominio.*;
import br.rui.cartoes.persistencia.*;
import br.rui.cartoes.persistencia.util.Leitor;
import br.rui.cartoes.util.Utils;

public class Fachada {
	
	public static void atualizarTaxas(Collection<Taxa> taxas) {
		for (Taxa taxa : taxas) {
			TaxaDB.update(taxa);
		}		
	}
	
	public static void atualizarExtrato(Extrato extrato){
		ExtratoDB.update(extrato);
	}
	
	public static void alterarLancamento(Lancamento lancamento, int codExtrato, int numLanc) {
		Extrato extrato = Fachada.findExtratoByCode(codExtrato);
		Lancamento lancamentoAntigo = Fachada.findLancamentoByNumLanc(numLanc);
		lancamento.setNumLanc(numLanc);		
		if(lancamento.getValorBruto() != lancamentoAntigo.getValorBruto()){
			Double tempBruto = lancamento.getValorBruto() - lancamentoAntigo.getValorBruto();
			Double tempLiquido = lancamento.getValorLiquido() - lancamentoAntigo.getValorLiquido();	
			extrato.setTotalBruto(extrato.getTotalBruto() + tempBruto);
			extrato.setTotalLiquido(extrato.getTotalLiquido() + tempLiquido);
			extrato.setTaxaADM((Double) Utils.aroundNumber(extrato.getTotalBruto() - extrato.getTotalLiquido()));
			ExtratoDB.update(extrato);			
		}
		LancamentoDB.update(extrato,lancamento);		
	}
	
	public static Collection<Faturamento> capturarFaturamento(){
		Properties props = Utils.getProps();
		return Leitor.lerFaturamento(props.getProperty("pathArquivos") + "ArquivoMTFiscal.txt");
	}
	
	public static Collection<LinhaArquivo> capturarDadosCartoes(Cliente cliente, String periodo){
		Collection<Taxa> taxasCliente = findTaxasByCliente(cliente);
		Collection<LinhaArquivo> dadosCartoes = new ArrayList<LinhaArquivo>();
		for (Taxa taxaCliente : taxasCliente) {
			int contadebito = taxaCliente.getContaDebito();
			Extrato extrato = findExtratosByTaxaPeriodo(taxaCliente, periodo);
			if(extrato != null)
				for (Lancamento lancamento : findLancamentosByExtrato(extrato)) {					
					dadosCartoes.add(new LinhaArquivo(lancamento.getDataApresentacao(),contadebito, 4200,lancamento.getValorBruto(),"19.04"));
				}
		}
		return dadosCartoes;
	}
	
	@SuppressWarnings("unchecked")
	public static int DiasMes(String p){
		int dias, mes, ano;
		String periodo [] = p.trim().split("/");
		mes = Integer.parseInt(periodo[0]);
		ano = Integer.parseInt(periodo[1]);
		dias = getNumberOfDaysInMonth(mes, ano);
		
		return dias;
	}

	public static Cliente findClienteByCode(int id){
		return ClienteDB.findByCode(id);
	}

	public static Cliente findClienteByName(String nome){
		return ClienteDB.findByName(nome);
	}

	public static Operadora findOperadoraByCode(int id){
		return OperadoraDB.findByCode(id);
	}

	public static Operadora findOperadoraByName(String nome){
		return OperadoraDB.findByName(nome);
	}

	public static Extrato findExtratoByCode(int id){
		return ExtratoDB.findByCode(id);
	}

	public static Collection<Extrato> findExtratosByTaxa(Taxa taxa) {
		return ExtratoDB.findByTaxa(taxa);
	}

	private static Extrato findExtratosByTaxaPeriodo(Taxa taxa , String periodo) {
		return ExtratoDB.findByTaxaPeriodo(taxa, periodo);
	}

	public static Collection<Lancamento> findLancamentosByExtrato(Extrato extrato){
		Collection<Lancamento> lancamentos = LancamentoDB.findByExtrato(extrato);
		return ordenarLancamentos(lancamentos);
	}

	public static Lancamento findLancamentoByNumLanc(int numLanc){
		return LancamentoDB.findByCode(numLanc);
	}

	@SuppressWarnings("unchecked")
	public static Collection<Taxa> findTaxasByCliente(Cliente cliente) {
		Collection<Taxa> todas = TaxaDB.findByAll();
		Collection<Taxa> taxas = new ArrayList<Taxa>();
		for (Taxa taxa : todas) {
			if(taxa.getCliente().getCodigo() == cliente.getCodigo())
				taxas.add(taxa);
		}
		return taxas;
	}

	@SuppressWarnings("unchecked")
	public static Taxa findTaxaByClienteOperadoraTipoTaxa(Cliente cliente, Operadora operadora, TipoTaxa tipotaxa) {
		Taxa taxa = new Taxa();
		taxa.setCliente(cliente);
		taxa.setOperadora(operadora);
		taxa.setTipotaxa(tipotaxa);
		return TaxaDB.findByTaxa(taxa);
	}

	public static TipoTaxa findTipoTaxaByName(String nomeTipoTaxa) {
		return TipoTaxaDB.findByName(nomeTipoTaxa);
	}

	private static int getNumberOfDaysInMonth(int month, int year){
		int out = 0;
		if(month==2 && ((year%400==0) || ((year%4==0) && (year%100!=0))))
	        out = 29;
	    else {
			if(month==1||month==3||month==5||month==7||month==8
					||month==10||month==12)
		        out = 31; 
			else{
				if(month==2)
			        out = 28;
				else
					out = 30;
			}	
		}
		return out;
	}

	public static Collection<LinhaArquivo> movimentoVista(Cliente cliente, String periodo){
		Collection<Faturamento> faturamentoMes = capturarFaturamento();
		Collection<LinhaArquivo> cartoes = capturarDadosCartoes(cliente, periodo);
		Collection<LinhaArquivo> linhasArquivo = new ArrayList<LinhaArquivo>();
		int numDias = DiasMes(periodo);
		SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yy");
		for (int dia=1;dia<=numDias;dia++){
			Date data = null;
			try {
				data = sdf.parse(dia+"/"+periodo);
			} catch (ParseException e) {
				e.printStackTrace();
			}
			Double totalCartoesDia = new Double(0);
			for (LinhaArquivo cartao : cartoes) {
				if(data.equals(cartao.getDia())){
					
					totalCartoesDia += cartao.getValor();
				}				
			}
			Double valorVista = new Double(0);
			for (Faturamento faturamento : faturamentoMes) {
				if (data.equals(faturamento.getDia())){
					valorVista = (Double) Utils.aroundNumber(faturamento.getValor() - totalCartoesDia);
					break;
				}
			}
			linhasArquivo.add(new LinhaArquivo(data,52,4200,valorVista,"10.22"));
		}	
		return linhasArquivo;
	}
		
	public static void novasTaxas(Collection<Taxa> taxas) {
		for (Taxa taxa : taxas) {
			Cliente cliente = findClienteByName(taxa.getCliente().getDescricao());
			Operadora operadora = findOperadoraByName(taxa.getOperadora().getNomeOperad());
			TipoTaxa tipotaxa = findTipoTaxaByName(taxa.getTipotaxa().getNomeTipoTaxa());
			novoTaxa(new Taxa(taxa.getValorTaxa(),cliente,operadora,tipotaxa,taxa.getContaDebito()));
		}
	}

	public static void novoCliente(Cliente cliente){
		ClienteDB.save(cliente);
	}
	
	public static void novoExtrato(Extrato extrato){
		ExtratoDB.save(extrato);
	}
	
	public static void novoLancamento(Lancamento lancamento, int codExtrato) {
		LancamentoDB.save(findExtratoByCode(codExtrato), lancamento);
		
	}

	public static void novosLancamentos(Extrato extrato, Collection<Lancamento> lancamentos){
		extrato.setCodExtrato(numExtrato());
		for (Lancamento lancamento : lancamentos) {
			LancamentoDB.save(extrato,lancamento);
		}
	}

	public static void novoOperadora(Operadora operadora){
		OperadoraDB.save(operadora);
	}
	
	public static void novoTipoTaxa(TipoTaxa tipotaxa) {
		TipoTaxaDB.save(tipotaxa);
	}
	
	public static void novoTaxa(Taxa taxa) {
		TaxaDB.save(taxa);
	}
	
	public static int numExtrato(){
		return ExtratoDB.numeroExtrato();
	}

	public static Collection<Cliente> obterClientes(){
		return ClienteDB.findByAll();
	}
	
	public static Collection<Operadora> obterOperadoras() {
		return OperadoraDB.findByAll();
	}
	
	public static Collection<Lancamento> obterLancamentos(){
		return LancamentoDB.findByAll();
	}
	
	public static Collection<TipoTaxa> obterTiposTaxa() {
		return TipoTaxaDB.findByAll();
	}
	
	public static Collection<Lancamento> ordenarLancamentos(Collection<Lancamento> lancamentos){
		ArrayList<Lancamento> resultado = (ArrayList<Lancamento>) lancamentos;
		for (int i=0; i < resultado.size() ; i++) {
			for (int j=0; j < resultado.size() ; j++) {
				if (resultado.get(i).getDataApresentacao().compareTo(resultado.get(j).getDataApresentacao()) < 0) {
					Lancamento temp = resultado.get(i);
					resultado.set(i, resultado.get(j));
					resultado.set(j,temp);					
				}
			}
		}		
		return resultado;
	}
	
	public static void removerLancamento(int codExtrato, int numLanc) {
		Extrato extrato = findExtratoByCode(codExtrato);
		Lancamento lancamentoAntigo = Fachada.findLancamentoByNumLanc(numLanc);		
		extrato.setTotalBruto(extrato.getTotalBruto() - lancamentoAntigo.getValorBruto());
		extrato.setTotalLiquido((Double) Utils.aroundNumber(extrato.getTotalLiquido() - lancamentoAntigo.getValorLiquido()));
		extrato.setTaxaADM((Double) Utils.aroundNumber(extrato.getTotalBruto() - extrato.getTotalLiquido()));
		LancamentoDB.delete(lancamentoAntigo);
		ExtratoDB.update(extrato);			
	}	
}
